home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * ADPCM Datatype, based on the sourcecode found in OS3.1 Native Developer Kit
- *
- * Written by Christian Buchner
- *
- ******************************************************************************
- * dispatch.c
- */
-
- #include "classbase.h"
-
- /*****************************************************************************/
-
- #define TARGET_SIZE 16384
-
- extern __asm ULONG DecompressADPCM2( register __a0 UBYTE *Source,
- register __d0 ULONG Length,
- register __a1 UBYTE *Destination,
- register __d1 ULONG JoinCode );
-
- extern __asm ULONG DecompressADPCM3( register __a0 UBYTE *Source,
- register __d0 ULONG Length,
- register __a1 UBYTE *Destination,
- register __d1 ULONG JoinCode );
-
- /*****************************************************************************/
-
- #define DEBUG 1
-
- #if DEBUG
-
- #define DB(x) x
-
- #include <stdarg.h>
- void __stdargs Error(struct ClassBase *cb,UBYTE *Msg,...)
- {
- va_list Arg;
- struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM debug message",0,"Okay"};
- va_start(Arg,Msg);
- Req.es_TextFormat=Msg;
- EasyRequestArgs(NULL,&Req,0,Arg);
- va_end(Arg);
- }
-
- #else
-
- #define DB(x)
-
- #endif
-
-
-
- /*****************************************************************************/
-
- Class *initClass (struct ClassBase * cb)
- {
- Class *cl;
-
- if (cl = MakeClass (LibName, SOUNDDTCLASS, NULL, NULL, 0L))
- {
- cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
- cl->cl_UserData = (ULONG) cb;
- AddClass (cl);
- }
-
- return (cl);
- }
-
- /*****************************************************************************/
-
- ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
- {
- struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
- ULONG retval = 0L;
-
- switch (msg->MethodID)
- {
- case OM_NEW:
- if (retval = DoSuperMethodA (cl, o, msg))
- {
- if (!(ConvertObjectData (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList)))
- {
- CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
- retval = NULL;
- }
- }
- break;
-
- /* Let the superclass handle everything else */
-
- default:
- retval = (ULONG) DoSuperMethodA (cl, o, msg);
- break;
- }
-
- return (retval);
- }
-
- /*****************************************************************************/
-
- struct ADPCMHeader
- {
- UBYTE Identifier[6]; /* $00 */
- ULONG Frequency; /* $06 */
- };
-
- /*****************************************************************************/
-
- BOOL ConvertObjectData (struct ClassBase * cb, Class * cl, Object * o, struct TagItem * attrs)
- {
- LONG ErrorCode=0;
- struct FileInfoBlock *fib;
- struct VoiceHeader *vhdr;
- STRPTR Title;
- BPTR FH;
- struct ADPCMHeader ADPCMHeader;
- ULONG Memory;
- UBYTE *Sample;
- ULONG Size;
- ULONG SampleSize;
-
- Title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
-
- getdtattrs (cb, o,
- SDTA_VoiceHeader, &vhdr,
- DTA_Handle, &FH,
- TAG_DONE);
-
- if (FH && vhdr)
- {
- /* Allocate a temporary file info block */
- if (!(fib = (struct FileInfoBlock *) AllocMem (sizeof (struct FileInfoBlock), NULL)))
- {
- ErrorCode=ERROR_NO_FREE_STORE;
- }
- else
- {
- /* Get the size of the file */
- if (ExamineFH (FH, fib))
- {
- Size = fib->fib_Size;
- }
- else
- {
- Seek (FH, 0, OFFSET_END);
- Size = Seek (FH, 0, OFFSET_BEGINNING);
- }
-
- /* Free the temporary file info block */
- FreeMem (fib, sizeof (struct FileInfoBlock));
-
- /* Calculate size from actual file length */
- Size-=sizeof(struct ADPCMHeader);
-
- /* Read in sample header */
- if (Read(FH,&ADPCMHeader,sizeof(struct ADPCMHeader))==sizeof(struct ADPCMHeader))
- {
- /* Check if it is a supported ADPCM format */
- if (ADPCMHeader.Identifier[5] != '2' && ADPCMHeader.Identifier[5] != '3')
- {
- ErrorCode=ERROR_OBJECT_WRONG_TYPE;
- }
- else
- {
- ULONG Bits;
-
- /* Retrieve the number of compression bits */
- if (ADPCMHeader.Identifier[5] == '2') Bits=2;
- if (ADPCMHeader.Identifier[5] == '3') Bits=3;
-
- /* Calculate the real sample size */
- if (Bits==2) SampleSize=Size*4 ;
- if (Bits==3) SampleSize=Size*8/3;
-
- /* sound.datatype V40 can replay */
- /* directly from Fast RAM */
-
- Memory = (SuperClassBase->lib_Version>39) ?
- MEMF_ANY : MEMF_CHIP;
-
- /* Allocate a buffer with the calculated size */
- if (!(Sample=AllocVec(SampleSize,Memory)))
- {
- ErrorCode=ERROR_NO_FREE_STORE;
- }
- else
- {
- UBYTE *ADPCMBuffer;
- ULONG ADPCMSize;
-
- if (Bits==2) ADPCMSize=(TARGET_SIZE+3)/4;
- if (Bits==3) ADPCMSize=(TARGET_SIZE+7)/8*3;
-
- if (ADPCMBuffer=AllocVec(ADPCMSize, MEMF_ANY))
- {
- ULONG Position,SampleOffset;
- ULONG JoinCode=0;
-
- for (Position=0,SampleOffset=0; Position<Size; )
- {
- ULONG Left=Size-Position;
- ULONG Do = Left < ADPCMSize ?
- Left : ADPCMSize ;
- LONG Got;
-
- if (Got=Read(FH, ADPCMBuffer, Do) != Do)
- {
- if (Got<0) ErrorCode=IoErr();
- else ErrorCode=ERROR_BAD_HUNK;
- break;
- }
-
- if (Bits==2) JoinCode=DecompressADPCM2(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
- if (Bits==3) JoinCode=DecompressADPCM3(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
-
- Position+=Do;
-
- if (Bits==2) SampleOffset+=Do*4;
- if (Bits==3) SampleOffset+=Do*8/3;
- }
-
- if (!ErrorCode)
- {
- /* Fill in the VoiceHeader */
- memset(vhdr,0,sizeof(struct VoiceHeader));
- vhdr->vh_OneShotHiSamples = Size;
- vhdr->vh_SamplesPerSec = ADPCMHeader.Frequency;
- vhdr->vh_Octaves = 1;
- vhdr->vh_Compression = CMP_NONE;
- vhdr->vh_Volume = 64;
-
- /* Tell the super-class about the attributes */
- setdtattrs (cb, o,
- DTA_ObjName, Title,
- SDTA_Sample, Sample,
- SDTA_SampleLength, SampleSize,
- SDTA_Period, (ULONG)(SysBase->ex_EClockFrequency*5)/(ULONG)vhdr->vh_SamplesPerSec,
- SDTA_Volume, 64,
- SDTA_Cycles, 1,
- TAG_DONE);
- }
- else
- {
- FreeVec(Sample);
- }
- FreeVec(ADPCMBuffer);
- }
- }
- }
- }
- }
- }
- if (ErrorCode)
- {
- SetIoErr(ErrorCode);
- return(FALSE);
- }
- return(TRUE);
- }
-
-
- /*****************************************************************************/
-
- ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
- {
- return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
- }
-
- /*****************************************************************************/
-
- ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
- {
- return (GetDTAttrsA (o, (struct TagItem *) & data));
- }
-